package com.watermark;

import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Matrix;
import android.graphics.Point;
import android.graphics.SurfaceTexture;
import android.hardware.Camera;
import android.opengl.GLSurfaceView;
import android.text.TextUtils;
import android.util.AttributeSet;

import com.watermark.core.CameraController;
import com.watermark.core.drawer.CameraDrawer;
import com.watermark.ui.PathUtil;

import java.io.File;

import javax.microedition.khronos.egl.EGLConfig;
import javax.microedition.khronos.opengles.GL10;

public class CameraView extends GLSurfaceView implements GLSurfaceView.Renderer, SurfaceTexture.OnFrameAvailableListener {

    private CameraDrawer mCameraDrawer;
    private CameraController mCamera;

    private int dataWidth = 0, dataHeight = 0;

    private boolean isSetParam = false;
    private final ICamera.Config mConfig = new ICamera.Config();

    private int cameraId;

    public CameraView(Context context) {
        this(context, null);
    }

    public CameraView(Context context, AttributeSet attrs) {
        super(context, attrs);
        init();
    }

    private void init() {
        /**初始化OpenGL的相关信息*/
        setEGLContextClientVersion(2);//设置版本
        setRenderer(this);//设置Renderer
        setRenderMode(RENDERMODE_WHEN_DIRTY);//主动调用渲染
        setPreserveEGLContextOnPause(true);//保存Context当pause时
        setCameraDistance(100);//相机距离

        /**初始化Camera的绘制类*/
        mCameraDrawer = new CameraDrawer();
        /**初始化相机的管理类*/
        mCamera = new CameraController();
    }

    private void open(int cameraId) {
        mCamera.close();
        mCamera.setConfig(mConfig);
        mCamera.open(cameraId);
        mCameraDrawer.setCameraId(cameraId);
        final Point previewSize = mCamera.getPreviewSize();
        dataWidth = previewSize.x;
        dataHeight = previewSize.y;
        SurfaceTexture texture = mCameraDrawer.getTexture();
        texture.setOnFrameAvailableListener(this);
        mCamera.setPreviewTexture(texture);
        mCamera.preview();
    }

    public void switchCamera() {
        cameraId = cameraId == 0 ? 1 : 0;
        open(cameraId);
    }

    /**
     * 设置视频录制的帧率
     *
     * @param frameRate 帧率
     */
    public void setFrameRate(int frameRate) {
        if (null != mCameraDrawer) mCameraDrawer.setFrameRate(frameRate);
    }

    /**
     * 设置最小分辨率
     *
     * @param pictureMinSize 默认：1080
     * @param videoMinSize   默认：720P
     */
    public void setMinSize(int pictureMinSize, int videoMinSize) {
        mConfig.minPictureWidth = pictureMinSize;
        mConfig.minPreviewWidth = videoMinSize;
    }

    public Point getPreviewSize() {
        return mCamera.getPreviewSize();
    }

    public Point getPictureSize() {
        return mCamera.getPictureSize();
    }

    /**
     * 设置视频采集的码率
     *
     * @param bitRate 默认：3500 000
     */
    public void setVideoBitRate(int bitRate) {
        if (null != mCameraDrawer) {
            mCameraDrawer.setVideoBitRate(bitRate);
        }
    }

    /**
     * @return 水印功能接口
     */
    public IWaterMark getWaterMarkDrawer() {
        return mCameraDrawer.waterMark;
    }

    @Override
    public void onSurfaceCreated(GL10 gl, EGLConfig config) {
        mCameraDrawer.onSurfaceCreated(gl, config);
        if (!isSetParam) {
            open(cameraId);
            stickerInit();
        }
        mCameraDrawer.setPreviewSize(dataWidth, dataHeight);
    }

    @Override
    public void onSurfaceChanged(GL10 gl, int width, int height) {
        mCameraDrawer.onSurfaceChanged(gl, width, height);
    }

    @Override
    public void onDrawFrame(GL10 gl) {
        if (isSetParam) {
            mCameraDrawer.onDrawFrame(gl);
        }
    }

    /**
     * 每次Activity onResume时被调用,第一次不会打开相机
     */
    @Override
    public void onResume() {
        super.onResume();
        if (isSetParam) {
            open(cameraId);
        }
    }

    /**
     * 摄像头聚焦
     */
    public void onFocus(Point point, Camera.AutoFocusCallback callback) {
        mCamera.onFocus(point, callback);
    }

    public int getCameraId() {
        return cameraId;
    }

    public int getBeautyLevel() {
        return mCameraDrawer.getBeautyLevel();
    }

    public void changeBeautyLevel(final int level) {
        queueEvent(new Runnable() {
            @Override
            public void run() {
                mCameraDrawer.changeBeautyLevel(level);
            }
        });
    }

    /**
     * 拍照 返回 bitmap 需自己保存到本地
     *
     * @param pictureResult bitmap回调
     */
    public void takePicture(ICamera.OnTakePictureResult<Bitmap> pictureResult) {
        if (null == mCamera) {
            if (null != pictureResult) pictureResult.onPictureResult(null);
            return;
        }
        mCamera.takePicture(new ICamera.OnTakePictureResult<byte[]>() {
            @Override
            public void onPictureResult(byte[] data) {
                Bitmap temp = BitmapFactory.decodeByteArray(data, 0, data.length);
                if (null == temp) {
                    if (null != pictureResult) pictureResult.onPictureResult(null);
                    return;
                }
                // 顺时针选择90
                Matrix matrix = new Matrix();
                matrix.preRotate(90);
                Bitmap bitmap = Bitmap.createBitmap(temp, 0, 0, temp.getWidth(), temp.getHeight(), matrix, false);
                temp.recycle();
                if (null != pictureResult) pictureResult.onPictureResult(bitmap);
            }
        });
    }

    /**
     * 拍照 并保存指定路径 回调成功状态
     *
     * @param path          路径
     * @param pictureResult 成功状态回调
     */
    public void takePicture(String path, ICamera.OnTakePictureResult<Boolean> pictureResult) {
        if (null == mCamera || TextUtils.isEmpty(path)) {
            if (null != pictureResult) pictureResult.onPictureResult(false);
            return;
        }
        mCamera.takePicture(new ICamera.OnTakePictureResult<byte[]>() {
            @Override
            public void onPictureResult(byte[] data) {
                Bitmap temp = BitmapFactory.decodeByteArray(data, 0, data.length);
                if (null == temp) {
                    if (null != pictureResult) pictureResult.onPictureResult(false);
                    return;
                }
                // 顺时针选择90
                Matrix matrix = new Matrix();
                matrix.preRotate(90);
                Bitmap bitmap = Bitmap.createBitmap(temp, 0, 0, temp.getWidth(), temp.getHeight(), matrix, false);
                temp.recycle();
                // draw water mark
                int w = bitmap.getWidth();
                int h = bitmap.getHeight();
                int size = Math.max(w, h);
                IWaterMark drawer = getWaterMarkDrawer();
                if (size <= 2560 && null != drawer && drawer.hasWaterMark()) {// 太大没法绘制 报oom
                    Bitmap nb = Bitmap.createBitmap(w, h, Bitmap.Config.ARGB_4444);
                    Canvas canvas = new Canvas(nb);
                    canvas.drawBitmap(bitmap, 0, 0, null);
                    bitmap.recycle();
                    drawer.drawWaterMark(canvas);
                    // 更新 bitmap
                    bitmap = nb;
                }
                boolean flag = PathUtil.saveBitmap2File(bitmap, path);
                if (null != pictureResult)
                    pictureResult.onPictureResult(flag && new File(path).exists());
            }
        });
    }

    /**
     * 开始录制
     *
     * @param path 文件路径
     */
    public void startRecord(String path) {
        mCameraDrawer.setSavePath(path);
        queueEvent(new Runnable() {
            @Override
            public void run() {
                mCameraDrawer.startRecord();
            }
        });
    }

    /**
     * 获取 Camera 实例
     *
     * @return camera
     */
    public ICamera getCamera() {
        return mCamera;
    }

    /**
     * 接受录制
     */
    public void stopRecord() {
        queueEvent(new Runnable() {
            @Override
            public void run() {
                mCameraDrawer.stopRecord();
            }
        });
    }

    public void resume(final boolean auto) {
        queueEvent(new Runnable() {
            @Override
            public void run() {
                mCameraDrawer.onResume(auto);
            }
        });
    }

    public void pause(final boolean auto) {
        queueEvent(new Runnable() {
            @Override
            public void run() {
                mCameraDrawer.onPause(auto);
            }
        });
    }

    private void stickerInit() {
        if (!isSetParam && dataWidth > 0 && dataHeight > 0) {
            isSetParam = true;
        }
    }

    @Override
    public void onFrameAvailable(SurfaceTexture surfaceTexture) {
        this.requestRender();
    }
}
